package com.dj.mingkong.common.util;

import com.dj.mingkong.common.exception.ExceptionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public enum CompareUtils {
    ;
    public static final Logger log = LoggerFactory.getLogger(JacksonUtil.class);
    private static final String DATE_FORMAT_SECOND = "yyyy-MM-dd HH:mm:ss";

    private CompareUtils() {
    }

    public static List<ComparisonResult> compareFields(Object obj1, Object obj2) {
        if (obj1 != null && obj2 != null && obj1.getClass() == obj2.getClass()) {
            try {
                List<String> ignoreList = getCompareFields(obj1.getClass());
                Map<String, String> descsMap = getFieldSwaggerValue(obj1.getClass());
                List<ComparisonResult> list = new ArrayList();
                Class<?> claz = obj1.getClass();
                PropertyDescriptor[] pds = Introspector.getBeanInfo(claz, Object.class).getPropertyDescriptors();
                PropertyDescriptor[] var7 = pds;
                int var8 = pds.length;

                for (int var9 = 0; var9 < var8; ++var9) {
                    PropertyDescriptor pd = var7[var9];
                    String name = pd.getName();
                    String label = (String) descsMap.get(name);
                    if (ignoreList.contains(name)) {
                        Method readMethod = pd.getReadMethod();
                        Object o1 = readMethod.invoke(obj1);
                        Object o2 = readMethod.invoke(obj2);
                        if (Objects.nonNull(o1) || Objects.nonNull(o2)) {
                            if (null != o1 && null != o2) {
                                if (compareField(o1, o2)) {
                                    setResult(o1, o2, name, label, list);
                                }
                            } else {
                                setResult(o1, o2, name, label, list);
                            }
                        }
                    }
                }

                return list;
            } catch (Exception var16) {
                log.error("对象比较失败, obj1:{}, obj2:{}", new Object[]{obj1, obj2, var16});
                throw ExceptionFactory.bizException("对象比较失败");
            }
        } else {
            return Collections.emptyList();
        }
    }

    private static List<String> getCompareFields(Class objectClass) {
        Field[] fields = objectClass.getDeclaredFields();
        List<String> map = new ArrayList();
        Field[] var3 = fields;
        int var4 = fields.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Field f = var3[var5];
            boolean annotationPresent2 = f.isAnnotationPresent(ComparisonFiled.class);
            if (annotationPresent2) {
                map.add(f.getName());
            }
        }

        return map;
    }

    private static Map<String, String> getFieldSwaggerValue(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        Map<String, String> map = new HashMap();
        Field[] var3 = fields;
        int var4 = fields.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Field f = var3[var5];
            boolean annotationPresent2 = f.isAnnotationPresent(ComparisonFiled.class);
            if (annotationPresent2) {
                ComparisonFiled name = (ComparisonFiled) f.getAnnotation(ComparisonFiled.class);
                String nameStr = name.value();
                map.put(f.getName(), nameStr);
            }
        }

        return map;
    }

    private static void setResult(Object o1, Object o2, String name, String label, List<ComparisonResult> list) {
        Object ot = null;
        String r1 = null;
        String r2 = null;
        if (Objects.nonNull(o1)) {
            ot = o1;
        } else if (Objects.nonNull(o2)) {
            ot = o2;
        }

        if (ot instanceof String) {
            r1 = objectToString(o1);
            r2 = objectToString(o2);
        } else if (ot instanceof BigDecimal) {
            log.debug("BigDecimal");
            r1 = objectToString(o1);
            r2 = objectToString(o2);
        } else if (ot instanceof Integer) {
            log.debug("Integer");
            r1 = objectToString(o1);
            r2 = objectToString(o2);
        } else if (ot instanceof Boolean) {
            log.debug("Boolean");
            r1 = booleanToString(o1);
            r2 = booleanToString(o2);
        } else if (ot instanceof Long) {
            log.debug("Long");
            r1 = objectToString(o1);
            r2 = objectToString(o2);
        } else if (ot instanceof LocalDateTime) {
            log.debug("LocalDateTime");
            r1 = localDateTimeToString(o1);
            r2 = localDateTimeToString(o2);
        }

        ComparisonResult result = new ComparisonResult();
        result.setKey(name);
        result.setPrevious(r1);
        result.setLater(r2);
        result.setLabel(label);
        list.add(result);
    }

    private static boolean compareField(Object o1, Object o2) {
        Boolean sign = false;
        Object ot = null;
        if (Objects.nonNull(o1)) {
            ot = o1;
        } else if (Objects.nonNull(o2)) {
            ot = o2;
        }

        if (ot instanceof String) {
            sign = !o1.equals(o2);
        } else if (ot instanceof BigDecimal) {
            log.debug("BigDecimal");
            sign = ((BigDecimal) o1).compareTo((BigDecimal) o2) != 0;
        } else if (ot instanceof Integer) {
            log.debug("Integer");
            sign = ((Integer) o1).compareTo((Integer) o2) != 0;
        } else if (ot instanceof Boolean) {
            log.debug("Boolean");
            sign = ((Boolean) o1).compareTo((Boolean) o2) != 0;
        } else if (ot instanceof Long) {
            log.debug("Long");
            sign = ((Long) o1).compareTo((Long) o2) != 0;
        } else if (ot instanceof LocalDateTime) {
            log.debug("LocalDateTime");
            sign = ((LocalDateTime) o1).compareTo((LocalDateTime) o2) != 0;
        }

        return sign;
    }

    private static String objectToString(Object obj) {
        return null == obj ? "" : obj.toString();
    }

    private static String booleanToString(Object obj) {
        if (null == obj) {
            return null;
        } else {
            return (Boolean) obj ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
        }
    }

    private static String localDateTimeToString(Object obj) {
        if (null == obj) {
            return null;
        } else {
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime ld = LocalDateTime.now();
            return df.format(ld);
        }
    }
}
